﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

using gma.System.Windows;

using AppUtils;
using PresentationUtils;
using System.IO;

namespace WindowsFormsApplication1
{
    public partial class frmMain : Form
    {
        Presentation presentation;

        UserActivityHook actHook;

        public frmMain()
        {
            InitializeComponent();

            disableNavigation();
            enableOpen();

            actHook = new UserActivityHook(false, true); // create an instance with global hooks
            // hook on events
            actHook.KeyDown += MyKeyDown;
        }

        private void enableClose()
        {
            btClose.Enabled = true;
            btOpen.Enabled = false;
        }

        private void btOpen_Click(object sender, EventArgs e)
        {
            OpenPresentation();
        }

        private void OpenPresentation()
        {
            if (!File.Exists(txtFile.Text))
            {
                string msg = "File not found: " + txtFile.Text;
                Logger.log(msg);
                MessageBox.Show(msg);
                return;
            }

            Logger.log("Start presentation: " + txtFile.Text);
            presentation = new Presentation(txtFile.Text);
            presentation.PresentationEnd += presentation_PresentationEnd;

            enableNavigation();
            enableClose();

            TopMost = true;
            timer.Enabled = true;
        }

        void presentation_PresentationEnd()
        {
            this.Invoke(new MethodInvoker(ClosePresentation));
        }

        private void enableNavigation()
        {
            btFirst.Enabled = true;
            btLast.Enabled = true;
            btNext.Enabled = true;
            btPrevious.Enabled = true;
            nudSlideNumber.Enabled = true;

            nudSlideNumber.Minimum = 1;
            nudSlideNumber.Maximum = presentation.NumberOfSlides + 1;
            lstSlides.Items.AddRange(presentation.SlideNames.ToArray());
            lstSlides.Items.Add("End-page");
        }

        private void btClose_Click(object sender, EventArgs e)
        {
            ClosePresentation();
        }

        private void ClosePresentation()
        {
            timer.Enabled = false;

            Logger.log("Close presentation");

            disableNavigation();

            presentation.ClosePresentation();
            presentation = null;
            enableOpen();
        }

        private void enableOpen()
        {
            btClose.Enabled = false;
            btOpen.Enabled = true;
        }

        private void disableNavigation()
        {
            btFirst.Enabled = false;
            btLast.Enabled = false;
            btNext.Enabled = false;
            btPrevious.Enabled = false;
            nudSlideNumber.Enabled = false;

            lstSlides.Items.Clear();
        }

        private void btPrevious_Click(object sender, EventArgs e)
        {
            Logger.log("Goto previous slide");
            presentation.Previous();
        }

        private void btNext_Click(object sender, EventArgs e)
        {
            Logger.log("Goto next slide");
            presentation.Next();
        }

        private void btFirst_Click(object sender, EventArgs e)
        {
            Logger.log("Goto first slide");

            presentation.First();
        }

        private void btLast_Click(object sender, EventArgs e)
        {
            Logger.log("Goto last slide");

            presentation.Last();
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (presentation != null)
            {
                presentation.ClosePresentation();
            }
        }

        private void nudSlideNumber_ValueChanged(object sender, EventArgs e)
        {
            presentation.GoTo((int)nudSlideNumber.Value);
        }

        private void lstSlides_SelectedIndexChanged(object sender, EventArgs e)
        {
            presentation.GoTo(lstSlides.SelectedIndex + 1);
        }

        public delegate void Decouple(KeyEventArgs e);

        public void MyKeyDown(object sender, KeyEventArgs e)
        {
            if (presentation == null)
                return;

            // TODO: decouple the events as we are not allowed to use them synchronously
            Logger.log(String.Format("Key {0}", e.KeyCode));
            Decouple decouple = new Decouple(OnDecouple);
            decouple.BeginInvoke(e, null, null);
        }

        public void OnDecouple(KeyEventArgs e)
        {
            Logger.log(String.Format("Key picked up {0}", e.KeyCode));
            if (e.KeyCode == Keys.PageDown)
            {
                presentation.Next();
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.PageUp)
            {
                presentation.Previous();
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.Home)
            {
                presentation.First();
                e.Handled = true;
            }
            else if (e.KeyCode == Keys.End)
            {
                presentation.Last();
                e.Handled = true;
            }
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            if (presentation == null)
                return;

            try
            {
                int nr = presentation.CurrentSlideNumber;

                nudSlideNumber.Value = nr;
                lstSlides.SelectedIndex = nr - 1;
            }
            catch (Exception) { }
        }

        private void btBrowse_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                txtFile.Text = openFileDialog.FileName;
            }
        }
    }
}
